/*
 * Copyright:  2018 smarabbit studio.
 *
 * Licensed under the Confluent Community License; you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 * http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under
 *  the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 *  either express or implied.  See the License for the specific language governing
 *  permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:    2020/8/16 下午6:23
 *
 */

package com.massyframework.beanskin.graphql.util;

import graphql.kickstart.servlet.context.DefaultGraphQLServletContext;
import graphql.kickstart.servlet.context.DefaultGraphQLWebSocketContext;

/**
 * {@link GraphQLContextUtils}, 执行环境工具类
 */
public abstract class GraphQLContextUtils {

    /**
     * 设置属性
     * @param context {@link Object}, GraphQL环境的上下文
     * @param name {@link String}, 参数名
     * @param value {@link Object},参数值
     */
    public static void setAttribute(Object context, String name, Object value){
        if (context == null) return;

        if (context instanceof DefaultGraphQLServletContext){
            ((DefaultGraphQLServletContext)context).getHttpServletRequest().setAttribute(name, value);
            return;
        }

        if (context instanceof DefaultGraphQLWebSocketContext){
            ((DefaultGraphQLWebSocketContext)context).getSession().getUserProperties().put(name, value);
            return;
        }
    }

    /**
     * 获取属性
     * @param context {@link Object}, GraphQL环境的上下文
     * @param name {@link String}, 属性名称
     * @return {@link Object}, 可能返回null.
     */
    public static Object getAttribute(Object context, String name){
        if (context == null) return null;
        if (context instanceof DefaultGraphQLServletContext){
            return ((DefaultGraphQLServletContext)context).getHttpServletRequest().getAttribute(name);

        }

        if (context instanceof DefaultGraphQLWebSocketContext){
           return  ((DefaultGraphQLWebSocketContext)context).getSession().getUserProperties().get(name);
        }

        return null;
    }

    /**
     * 获取属性,并转换为{@code requiredType}类型返回
     * <p>如果属性不支持要求的类型，则返回null.</p>
     * @param context {@link Object}, GraphQL环境的上下文
     * @param name {@link String}, 属性名称
     * @return {@link T}, 可能返回null.
     */
    public static <T> T getAttribute(Object context, String name, Class<T> requiredType){
        Object result = getAttribute(context, name);
        return result == null ? null :
                 requiredType.isAssignableFrom(result.getClass()) ? requiredType.cast(result) : null;
    }

    /**
     * 移除属性
     * @param context {@link Object}, GraphQL环境的上下文
     * @param name {@link String}, 属性名称
     * @return {@link Object},可能返回null.
     */
    public static Object removeAttribute(Object context, String name){
        if (context == null) return null;
        if (context instanceof DefaultGraphQLServletContext){
            Object result = ((DefaultGraphQLServletContext)context).getHttpServletRequest().getAttribute(name);
            if (result != null) {
                ((DefaultGraphQLServletContext) context).getHttpServletRequest().removeAttribute(name);
            }
            return result;
        }

        if (context instanceof DefaultGraphQLWebSocketContext){
            return  ((DefaultGraphQLWebSocketContext)context).getSession().getUserProperties().remove(name);
        }

        return null;
    }

    /**
     * 移除指定类型的属性
     * <p>如果属性不支持指定类型，则不执行移除，并返回null.</p>
     * @param context {@link Object}, GraphQL环境的上下文
     * @param name {@link String}, 属性名称
     * @param requiredType {@link Class}, 要求属性支持的类型
     * @param <T>
     * @return {@link T}, 可能返回null.
     */
    public static <T> T removeAttribute(Object context, String name, Class<T> requiredType){
        if (context == null) return null;

        if (context instanceof DefaultGraphQLServletContext){
            Object result = ((DefaultGraphQLServletContext)context).getHttpServletRequest().getAttribute(name);
            if (result != null){
                if (requiredType.isAssignableFrom(result.getClass())){
                    ((DefaultGraphQLServletContext)context).getHttpServletRequest().removeAttribute(name);
                }

                return requiredType.cast(result);
            }

            return null;
        }

        if (context instanceof DefaultGraphQLWebSocketContext){
            Object result = ((DefaultGraphQLWebSocketContext)context).getSession().getUserProperties().get(name);
            if (result != null){
                if (requiredType.isAssignableFrom(result.getClass())){
                    ((DefaultGraphQLWebSocketContext)context).getSession().getUserProperties().remove(name);
                }
                return requiredType.cast(result);
            }
            return null;
        }

        return null;
    }
}
